home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / tclMotif-1.4 / doc / userman.txt < prev   
Encoding:
Text File  |  1995-06-29  |  31.5 KB  |  779 lines

  1.  
  2. Disclaimer
  3.  
  4. This user manual is shockingly short.
  5. The whole system should currently only be attempted by someone who is brave,
  6. knows either Motif or Tk, or preferably knows both.
  7.  
  8. Introduction
  9.  
  10. This is a binding of the Tcl language to the Motif widgets.
  11. Tcl is an interpreted language originally intended for use as a command
  12. language for other applications. It has been used for that, but has also
  13. become useful as a language in its own right.
  14.  
  15. Tcl has been extended by a set of widgets called Tk. The Tk widgets are not
  16. based on the Xt Intrinsics, but are built above Xlib. They allow an easy
  17. way of writing X Window applications.
  18.  
  19. The standard set of widgets in the X world is now the Motif set. This forms
  20. a large set of widgets, and these have been through a large amount of
  21. development over the last five years. Use of this set is sometimes a
  22. requirement by busineses, and other widget sets try to conform to them in
  23. appearance and behaviour.
  24.  
  25. This system allows the programmer to use the Motif widgets instead of the
  26. Tk widgets from Tcl programs. This increases programmer choices, and allows
  27. comparison of the features of both Tcl and the Tk/Motif style of widget
  28. programming.  The binding gives the full set of Motif widgets, accessible
  29. through the simple interpreted Tcl language.
  30.  
  31. Acknowledgments
  32.  
  33. This system is based on Tk for the style of widget programming. This was
  34. because it provides a good model, but it also allows the Tcl programmer to
  35. move relatively easily between Tk and Motif programming. An alternative
  36. style of binding to Motif is used in the WKSH system, which performs a
  37. similar sort of role for the Korn Shell. The WKSH is much closer to the C
  38. API for Xt than is Tk. An intermediate style is provided
  39. by the Wafe binding of Xt-based widgets to tcl.
  40.  
  41. The documentation is incomplete (and is likely to be for a very
  42. long time). Consequently the programmer will probably need to refer to the
  43. Motif Programers Reference Manual. The system has been designed so that
  44. it is relatively easy to translate the C-based information in this manual
  45. into the corresponding Tcl information. This has been aided by the
  46. consistency with which Motif has been implemented in certain areas.
  47.  
  48. Running Tcl/Motif programs
  49.  
  50. Tcl/Motif programs may be run by the `moat' (MOtif And Tcl) interpreter.
  51. When called with no arguments it reads Tcl commands from standard input.
  52. When called by
  53.  
  54. moat file-name
  55.  
  56. it reads Tcl commands from `file-name', executes them and then enters the
  57. Tm event loop.  This is similar to the Tk `wish' and the concept was
  58. borrowed from there. However, it does not use the wish prefix of ``-file''
  59. but instead the standard form from ``tclsh''.
  60.  
  61. Depending on your shell interpreter, you will probably be able to run 
  62. Tcl/Motif programs as standalone programs. If your moat interpreter is
  63. installed in say `/usr/local/bin/moat', make this the first line of your
  64. executable program:
  65.  
  66. #!/usr/local/bin/moat
  67.  
  68. Widget naming
  69.  
  70. Widgets are visual objects that exist on the screen.
  71. They are organised as a hierarchy, with the application itself forming the
  72. root of this hierarchy.
  73. The naming of objects within this hierarchy is similar to the ``absolute
  74. path names'' of Unix files with a `.' replacing the `/' of Unix.
  75. The application itself is known as `.'.
  76. A Form in the application may be known as `.form1'.
  77. A Label in this form may be `.form1.okLabel', and so on.
  78. Note that Xt requires that `.' can only have one child
  79. (except for dialogs).
  80. This naming convention is the same as in Tk.
  81.  
  82. Widget creation
  83.  
  84. Widgets belong to classes, such as Label, PushButton or List.
  85. For each class there is a creation command which takes the pathName of the
  86. object as first argument with optional further arguments:
  87.  
  88. xmForm .form1
  89.  
  90. xmLabel .form1.okLabel
  91.  
  92. xmLabel .form1.cancelLabel -labelString "Get rid of me"
  93.  
  94. creates a Form `form1' as child of `.', and two Labels `okLabel' and
  95. `cancelLabel' as children of `form1'. The `cancelLabel' has additional
  96. arguments that set the labelString to "Get rid of me".
  97.  
  98. The set of classes generally mirrors the Motif set.
  99. Some widgets in Motif and Xt are not accessible from this binding because
  100. they are intended for use in inheritance only, such as Core and Primitive.
  101. The types of widgets that can be created using this include the primitive
  102. widgets:
  103.  
  104. xmArrowButton - a simple arrow, 
  105. xmDrawnButton - a button with graphics in it
  106. xmCascadeButton - for use in menus
  107. xmToggleButton - for on/off boxes
  108. xmLabel - a fixed piece of text
  109. xmText - a text editor
  110. xmTextField - a one line text editor
  111. xmSeparator - for simple lines between objects
  112. xmList - a list selector
  113. xmScrollBar - a horizontal or vertical scrolling bar
  114.  
  115. and the Manager widgets:
  116.  
  117. xmBulletinBoard - simple geometry management
  118. xmRowColumn - regular geometry management
  119. xmPanedWindow - multiple panes separated by sashes
  120. xmFrame - a 3-D border
  121. xmScale - a slider on a scale
  122. xmScrolledWindow - for displaying a clip view over an area
  123. xmMainWindow - contains a menu bar and the main application windows
  124. xmForm - for irregular geometry arrangements
  125. xmMessageBox - message display area
  126. xmCommand - a command entry area with a history list
  127. xmFileSelectionBox - selection of a file from a list
  128.  
  129. Motif has two special commands for creating a ScrolledList and a ScrolledText.
  130. These commands actually create a pair of widgets: a List or Text inside a
  131.  ScrolledWindow. To create such widgets is similar to the C binding: the
  132. List (or Text) widget name is given. If the parent ScrolledWindow is required
  133. then you have to call the ``parent'' method on the List or Text widget.
  134.  
  135. xmForm .form1
  136.  
  137. xmScrolledList .form1.list2
  138.  
  139. [.form1.list2 parent] setValues -attachTop attach_form
  140.  
  141. Motif also has convenience functions that create dialogs.
  142. These don't create ordinary widgets, but Motif pretends that they do.
  143. Tm follows this, and allows you to use commands such as
  144.  
  145. xmQuestionDialog .askMe
  146.  
  147. to create such dialogs. When you have to destroy such widgets, destroy the
  148. parent:
  149.  
  150. [.askMe parent] destroy
  151.  
  152. This set of dialogs includes:
  153.  
  154. xmBulletinBoardDialog - a dialog with arbitrary contents, based on bulletinBoard
  155. xmFileSelectionDialog - a dialog based on fileSelectionBox
  156. xmFormDialog - a dialog based on form
  157. xmInformationDialog - a dialog displaying information
  158. xmMessageDialog - a dialog showing a message
  159. xmPromptDialog - a dialog with a prompt area
  160. xmQuestionDialog - a dialog asking a question
  161. xmSelectionBoxDialog - a dialog based on selectionBox
  162. xmWarningDialog - a dialog showing a warning message
  163. xmWorkingDialog - a dialog showing a busy working message
  164.  
  165. For example, consider a rowColumn containing two labels and a pushButton,
  166. where the rowColumn is inside a mainWindow:
  167.  
  168. xmMainWindow .main
  169. xmRowColumn .main.rowcol
  170. xmLabel .main.rowcol.label1
  171. xmLabel .main.rowcol.label2
  172. xmPushButton .main.rowcol.btn
  173.  
  174. Not all objects used in the OSF C library are supported: gadgets are 
  175. not supported by Tm, nor are the ``simple'' menu functions.
  176.  
  177. Managing widgets
  178.  
  179. Before a widget cn be displayed, it must be brought under the geometry
  180. control of its parent (similar to placing a Tk widget). This can be done
  181. by the ``manageChild'' method of each widget, but also by an optional 
  182. third command to each widget creation function, similar to the
  183. XtCreateManagedWidget functions. For example,
  184.  
  185. xmLabel .l1 managed
  186. xmLabel .l2
  187. .l2 manageChild
  188.  
  189. Documentation
  190.  
  191. The widgets described above not only look and act the same as the Motif
  192. widgets, they *are* the Motif widgets. So descriptions of them in any Motif
  193. book or reference apply. In the Motif Programmers Reference these widgets
  194. are described under the same names, prefixed by ``Xm'' as in XmPushButton.
  195. The creation functions are prefixed by ``XmCreate'' as in
  196. XmCreatePushButton.
  197.  
  198. The Tm documentation is at present incomplete. There should be a man page
  199. for each widget, under the name of the widget prefixed by ``Tm'' as in
  200. TmPushButton.
  201.  
  202. Widget commands
  203.  
  204. Creating a widget actually creates a Tcl command known by its pathName.
  205. This command may be executed with at least one parameter 
  206. to either change the behavior of the object
  207. or the value of its components, or to get information about the object.
  208. The parameter acts like a ``method'' to the object, and specifies an action
  209. that it should perform. The parameters that are recognised by every object
  210. include:
  211.  
  212. unmanageChild - remove the object from its parents geometry management, which
  213. makes it disappear from the display
  214.  
  215. manageChild - bring it back under geometry management and make it appear again
  216.  
  217. mapWidget - remain under geometry management, but make it disappear
  218.  
  219. unmapWidget - make it reappear
  220.  
  221. realizeWidget - create windows for the widget and its children (usually used only by ``.'')
  222.  
  223. getValues - obtain properties of the widget
  224.  
  225. setValues - set properties of the widget
  226.  
  227. parent - return the parent of the widget
  228.  
  229. destroyWidget - destroy the widget and all its children
  230.  
  231. setSensitive - change the sensitivity of the widget to responses to input
  232.  
  233. callActionProc - call an action procedure (usually used in regression testing)
  234.  
  235. dragStart - used in drag and drop
  236.  
  237. dropSiteRegister - used in drag and drop
  238.  
  239. getGC - return a graphics context (used for drawing in DrawingArea and DrawnButton)
  240.  
  241. any string ending in ``Callback'' - register Tcl code to be executed when
  242. something happens to the widget.
  243.  
  244. For example,
  245.  
  246. .form1.okLabel unmanageChild
  247.  
  248. .form1.okButton activateCallback {puts stdout "I was pushed into it..."}
  249.  
  250. Unmanaging a widget removes it from the display, and from the geometry
  251. management of its parent. Managing it reverses this. The other methods
  252. are explained later.
  253.  
  254. Other widget commands
  255.  
  256. The root widget ``.'' has a number of commands unique to it. Generally,
  257. these are commands that use the application context (moat only uses one
  258. application context). These commands include
  259.  
  260. addInput
  261. removeInput
  262. mainLoop
  263.  
  264. Both Text and List have a large number of other commands due to the
  265. complexity of these widgets. Other widgets also have special methods.
  266. See the manual pages for further information.
  267.  
  268. Widget resources
  269.  
  270. Each widget has a set of resources that can be set at creation time,
  271. set at a later time, or queried for their value. For example, a pushButton
  272. has a width and a height, a labelString that is the text that will show in
  273. it, a foreground and background colour, a fontList giving the set of fonts
  274. that will be used to draw the text, and so on.
  275.  
  276. All resource names are prefixed by a minus `-' in Tcl programs, for 
  277. consistency with the Tk widgets. 
  278. On setting a value, all resources take the next
  279. word as value, and on getting a value the next word is the name of a variable
  280. to  store the value in.
  281.  
  282. On creation, the resource/value pairs come after the widget pathName, as in
  283.  
  284. xmLabel .okLabel -labelType pixmap -labelPixmap xlogo32
  285.  
  286. which sets the labelType to pixmap and the labelPixmap to xlogo32.
  287.  
  288. Resources can be set at any time using the setValues method
  289.  
  290. .text setValues -editMode editable -value "Some text"
  291.  
  292. which ensures that the text widget can be edited, and sets a
  293. value of "Some text".
  294.  
  295. Resources can be obtained from the widget using the getValues method.
  296. For example
  297.  
  298. .fileSelectionBox getValues -dirSpec file_selected -directory dir
  299.  
  300. stores in the Tcl variable file_selected the filename that was entered, and
  301. in the Tcl variable dir the directory in which the file selection occurred.
  302.  
  303. Each widget inherits resources from superclasses. For example, Label is a
  304. subclass of Primitive which in turn is a subclass of Core.  From Core it
  305. inherits resources such as background, height and width.  From Primitive it
  306. inherits resources such as foreground.  It is neccessary to look at these
  307. superclasses.  In addition, each class adds extra resources.  For example,
  308. Label has the additional resources labelType, labelPixmap and labelString,
  309. among others.
  310.  
  311. Resources are documented in the Tm man page for each widget. This
  312. documentation is weak.
  313.  
  314. Resource names can be obtained from the Motif documentation for each
  315. widget. The Motif documentation for each widget has a set of tables
  316. headed ``Resource Set''.  In the table of resources, the names of these
  317.  are given prefixed by ``XmN'', such as XmNeditMode.  Drop the prefix
  318. to get the Tcl resource name. Case is important here.
  319.  
  320. Resource values can also be obtained from the Motif documentation.  For
  321. each resource look at its type.  Types such as Dimension and Position are
  322. numeric types, and along with int types need an integer value.  In the Tcl
  323. program they are implemented as Tcl Strings, as is everything.  In fact,
  324. all resource values are Tcl strings.  Pixmaps, for example, are the string
  325. name of a pixmap such as ``xlogo32''.  Pixel is a color such as ``blue'',
  326. or a hexadecimal representation of the color.  Types such as the
  327. arrowDirection of an ArrowButton form a discrete set with values listed as
  328. XmARROW_UP, XmARROW_DOWN, etc.  For these types, drop the ``Xm'' and use
  329. the rest of the string as the value.  On setting values, case is not
  330. important but on getting values the string will be lower case for these
  331. discrete types.
  332.  
  333. So for example, a pushButton may have
  334.  
  335. xmPushButton .btn -width 100
  336. .btn setValues -labelString "Push Me" -foreground red
  337. .btn getValues -background bg
  338. puts stdout "background colour is $bg"
  339.  
  340. Callbacks
  341.  
  342. When the user does things to a widget, it may cause the widget to take certain
  343. actions.  For example, when a button is pressed it changes appearance to
  344. look pressed in. Some of these actions can have Tcl code attached to them,
  345. so that the Tcl code is evaluated when the action is performed. The Tcl
  346. code is attached to a ``callback'' by a widget command.  For example, a
  347. pushButton has an activateCallback that is called when the user presses and
  348. releases the left mouse button inside the widget; it has an armCallback
  349. that is called when the user presses the mouse button; it has a
  350. disarmCallback that is called when the user releases the mouse button
  351. inside the widget.
  352.  
  353. Tcl code is attached to a callback by giving it as the second argument to the
  354. appropriate widget methodod. For example,
  355.  
  356. .btn armCallback {puts stdout "Stop squashing me!!!"}
  357. .btn disarmCallback {puts stdout "That's better!"}
  358.  
  359. The names of the callbacks available for a particular widget are derived
  360. from the resource documentation for the Motif widget.  Each callback ends
  361. with the string "Callback" in its name.  Drop the "XmN" from the Motif
  362. description to gain the widget command.  Callbacks are treated differently
  363. to other resources because the Xt toolkit treats them differently - the
  364. resource is not meant to be handled directly by any ordinary application.
  365.  
  366. Callback substitutions
  367.  
  368. Motif supplies information to each callback function that is specific to
  369. the widget type.  Generally this is not of much interest. However, for some
  370. widgets such as List this is used to supply important information, such as
  371. what item in the List was selected! To make this available to the Tcl
  372. callback function a pattern substitution mechanism may be used.  Any ``%''
  373. followed by a word will be treated as a pattern for potential substitution.
  374. For example, ``%item'' in a List will be replaced by the item selected,and
  375. ``%item_position'' will be replaced by its position in the list.
  376. An example list callback is
  377.  
  378. .list singleSelectionCallback {print_info %item %item_position}
  379.  
  380. proc print_info {item position} {
  381.  
  382.     puts stdout "item was $item, at position $position"
  383.  
  384. }
  385.  
  386. The substitutions allowed may be found from the Motif documentation.  In
  387. the description of callback information one or more structures will be
  388. defined. The field names in these structures are the names used in ``%''
  389. substitutions. Not all of the possibilities are implemented yet.  
  390. This is admittedly obscure and not easy to find, so the Tm
  391. documentation needs to fix this lack. If you feel upto reading C code
  392. instead, the upto date ``list'' is found in the file ``tmExpand.c''
  393.  
  394. Text verify callbacks
  395.  
  396. The Text widget allows special processing by the application of text entered.
  397. After a character has been typed, or text pasted in, initial processing by
  398. the Text widget determines what the user is entering. This text is then
  399. passed to special callback functions. These functions can make copies of
  400. the text, can alter it, or can set a flag to say do not display it. Simple
  401. uses for this are a password entry widget that reads the text but does not
  402. display it (or echoes `*' instead), or text formatting widgets.
  403.  
  404. The callback mechanism for this is basically the same as for  other
  405. callbacks, and similar sorts of substitutions are allowed. For example, the
  406. term %currInsert is replaced by the current insertion position. Other
  407. substitutions do not give a value, but rather give the name of a tcl
  408. variable. This allows the application to change the value as required. The tcl
  409. variable is in the context of the callback caller, so upvar should be used. For
  410. example, to turn off echoing of characters, the following should be done:
  411.  
  412. .text modifyVerifyCallback {no_echo %doit}
  413.  
  414. proc no_echo {doit} {
  415.   upvar 1 $doit do_insert
  416.  
  417.   set do_insert false
  418. }
  419.  
  420. (Actually, the tcl variable here is the global variable _Tm_Text_Doit. For
  421. this reason, variables beginning with _Tm_ are reserved for use by the Tm 
  422. library.)
  423.  
  424. Other substitutions that can be made in the modifyVerify callback are ``ptr''
  425. and ``length''. ptr is the string that is being entered, and length is its
  426. length. These may be changed by the callback procedure. For example, to 
  427. change all incoming text to uppercase, 
  428.  
  429. proc allcaps {ptr length} {
  430.   upvar 1 $ptr p
  431.   upvar 1 $length l
  432.  
  433.   if {$l == 0} return
  434.   set upper [string toupper $p]
  435.   set p $upper
  436. }
  437.  
  438. .text modifyVerifyCallback {allcaps %ptr %length}
  439.  
  440. Dialogs
  441.  
  442. Selection Box has a number of component children, which may be managed or unmanaged
  443. by the application. If the SelectionBox was named .sel, these are
  444.  
  445.     .sel.Items
  446.     .sel.ItemsList
  447.     .sel.Selection
  448.     .sel.Text
  449.     .sel.Separator
  450.     .sel.Apply
  451.     .sel.Cancel
  452.     .sel.Help
  453.     .sel.OK
  454.  
  455. The same applies to Message Box. These widgets are often managed or unmanaged
  456. to add or remove elements from a dialog. Motif gives no information about
  457. types of these widgets, so managing and unmanaging are really the only two
  458. operations that you should perform on these widgets.
  459.  
  460. Actions
  461.  
  462. Actions may be added to a widget in a similar way to the C version. In that
  463. you define an action in a translation table which is set in the widget. You
  464. then have to register the action with the toolkit so that it is attached to
  465. a C function. In this binding, the tcl code is placed as the arguments to the
  466. action in the translation table. Regisitering the action links a generic action
  467. handler which in turn will handle the tcl code. Here is what it looks like to
  468. add action to make an arrow turn left or right when `l' or `r' is pressed:
  469.  
  470. xmArrowButton .arrow managed
  471.  
  472. .arrow setValues -translations \
  473.     "<Key>r: exec(arrow_direction %w arrow_right) \n\
  474.          <Key>l: exec(\"arrow_direction %w arrow_left\")"
  475.  
  476. proc arrow_direction {arrow direction} {
  477.   puts stdout "Changing direction to $direction"
  478.   $arrow setValues -arrowDirection $direction
  479. }
  480.  
  481. The pattern %w is substituted for the name of the tcl widget. More 
  482. substitutions may be added in later (eg for x, y).
  483.  
  484. The method callActionProc is available for every widget. The purpose of this
  485. is to allow regresion tests to be performed. This takes an action as further
  486. parameter, using the usual Xt syntax. For example, to simulate the return key
  487. press occurring within an arrow button, call the ArmAndActivate() action:
  488.  
  489. .arrow callActionProc ArmAndActivate()
  490.  
  491. This sends (by default) a ClientMessage event to the widget. Most widgets
  492. ignore the event for most events, so this is sufficient. Some actions
  493. require event detail, though. For example, when a mouse button release occurs,
  494. the widget checks to see if the release occurred *inside* or *outside* the
  495. widget. It does this because if the event occurs inside, then the callbacks
  496. attached to the Activate() action are invoked, but otherwise they are not.
  497. To handle this, an event of type ButtonPress, ButtonRelease, KeyPress or
  498. KeyRelease can be prepared with some fields set. For example, a ButtonRelease
  499. occurring within the arrow can be sent by
  500.  
  501. .arrow callActionProc Activate() \
  502.         -type ButtonPress \
  503.         -x 0 -y 0
  504.  
  505. Some of the Text manipulation actions require a KeyPress event, such as
  506. self-insert(), which inserts the character pressed. The character is
  507. actually encoded as a keycode, which is a hardware dependant code, too
  508. low-level for this binding. To prepare such an event, this toolkit uses
  509. *keysyms* which are abstractions for each type of key symbol. The alphanumerics
  510. have simple representations as themselves (`a', `A', `2', etc). Others have
  511. symbolic names (`space', `Tab', `BackSpace', etc). These are derived from
  512. the X Reference manual or in the file <X11/keysymdefs.h> by removing the
  513. prefix ``XK_''.
  514.  
  515. For example, to insert the three characters `A a' into .text
  516.  
  517. .text callActionProc self-insert() \
  518.         -type KeyPress \
  519.         -keysym A
  520. .text callActionProc self-insert() \
  521.         -type KeyPress \
  522.         -keysym space
  523. .text callActionProc self-insert() \
  524.         -type KeyPress \
  525.         -keysym a
  526.  
  527.  
  528. The set of actions that require this level of preparation of the X event
  529. is nowhere documented explicitly. You have to read between the lines of
  530. the Motif documentation, or guess at behaviour (or read Motif source code).
  531.  
  532. The Motif world
  533.  
  534. In earlier versions than 0.8, a specialised interpreter was used, much like
  535. Tk's ``wish''. To conform to the new extension methods of tcl7.0, this was
  536. changed. Part of the result of this is that the Xt world has to be explicitly
  537. brought into existence. This also allows the class and fallback resources to
  538. be set, and leaves hooks for things like setting the application icon
  539. to be added later to this binding.
  540.  
  541. The three world manipulation functions added are
  542.  
  543. xtAppInitialize
  544. . realizeWidget
  545. . mainLoop
  546.  
  547. xtAppInitialize may take parameters of -class and -fallback_resources. If
  548. the class option is omitted, the binding will deduce a class by capitalising
  549. the first letter of the application name, and - if it was an `x' - also
  550. capitalising the second letter.
  551.  
  552. Examples
  553.  
  554. A number of examples are in the programs directory. Those with `DH' in
  555. them duplicate the examples in Dan Heller's ``Motif Programming Manual'',
  556. O'Reilly & Associates Inc. Those that are just numbered are undocumented
  557. test programs. They may not behave in a nice way, but that doesn't matter
  558. too much.
  559.  
  560. The following example is in the programs directory as progEG.
  561. The typical structure of a Motif program is that the top-level object is a
  562. mainWindow. This holds a menu bar, and a container object such as a form or
  563. a rowColumn which in turn holds the rest of the application objects. So a
  564. mainWindow with a list and some buttons in a form would be created by
  565.  
  566. xtAppInitialize -class Example
  567.  
  568. xmMainWindow .main
  569. xmForm .main.form
  570. xmList .main.form.list
  571. xmPushButton .main.form.btn1
  572. xmPushButton .main.form.btn2
  573.  
  574. The form acts as what is called the ``workWindow'' of the mainWindow. This
  575. resource would be set by
  576.  
  577. .main setValues -workWindow .main.form
  578.  
  579. Values would also be set into the list and buttons:
  580.  
  581. .main.form.list setValues \
  582.     -itemCount 3 \
  583.     -items "one, two, three" \
  584.     -selectionPolicy single_select
  585. .main.form.btn1 setValues -labelString Quit
  586. .main.form.btn2 setValues -labelString "Do nothing"
  587.  
  588. Behaviour would be set by a callback function
  589.  
  590. .main.form.btn1 activateCallback {exit 0}
  591. .main.form.list singleSelectionCallback {puts stdout "Selected %item"}
  592.  
  593. Geometry would be set for the form, to put the objects in their correct
  594. relation to each other. Suppose this is the list on the left, with the two
  595. buttons one under the other on the right:
  596.  
  597. .main.form.list setValues \
  598.     -topAttachment attach_form \
  599.     -leftAttachment attach_form \
  600.     -bottomAttachment attach_form
  601. .main.form.btn1 setValues \
  602.     -topAttachment attach_form \
  603.     -leftAttachment attach_widget \
  604.     -leftWidget .main.form.list
  605. .main.form.btn2 setValues \
  606.     -topAttachment attach_widget \
  607.     -topWidget .main.form.btn1 \
  608.     -leftAttachment attach_widget \
  609.     -leftWidget .main.form.list \
  610.  
  611. Finally, windows are created and the main event loop is entered:
  612.  
  613. . realizeWidget
  614. . mainLoop
  615.  
  616. Drag and Drop
  617.  
  618. Drag and drop was introduced into Motif 1.2. It is complicated. We shall
  619. first look at the drop side. A widget has to first register itself as a
  620. drop site, so that when an attempt is made to drop something on it, it will
  621. try to handle it. This registration is done by the widget method
  622. dropSiteRegister. This registration must include tcl code to be executed
  623. when a drop is attempted, and this is done using the resource dropProc. The
  624. first part of what makes D&D hard is that you have potentially two
  625. different applications attempting to communicate, one dropping and the
  626. other accepting the drop. A protocol is needed between these, so that they
  627. share a common language. This is done in registration by saying what types
  628. of protocol are used, and how many there are. This is done using X atoms,
  629. and the major ones are COMPOUND_TEXT, TEXT and STRING. Thus registration is
  630. done, for example, by
  631.  
  632. .l dropSiteRegister \
  633.         -dropProc {startDrop %dragContext} \
  634.         -numImportTargets 1 \
  635.         -importTargets COMPOUND_TEXT
  636.  
  637. This allows .l to be used as a drop site, accepting COMPOUND_TEXT only.
  638. Multiple types are allowed, using the Motif list structure of elements
  639. separated by commas as in "COMPOUND_TEXT, TEXT, STRING".
  640. When a drop occurs, the procedure startDrop is called, with one substituted
  641. parameter. This parameter is a dragContext, which is a widget created to
  642. by Motif to handle the drag part of all this. You must include this
  643. parameter, or the next stage doesn't get  off the ground.
  644.  
  645. When a drag actually occurs, Motif creates a dragContext widget. A drag is
  646. started by holding down the middle button in a drag source, which is
  647. discussed later. The dragContext widget contains information about the drag
  648. source, which is to be matched up against where the drop occurs. When the
  649. drop occurs, by releasing  the middle button, the tcl code registered as
  650. dropProc is executed. This should have the dragContext widget as parameter.
  651. This code may try to determine if the drop should go ahead, but more
  652. normally will just act as a channel through to the actual information
  653. transfer. Still here? Good. The dragProc doesn't actually do the
  654. information transfer, it just determines whether or not it is possible, and
  655. if it is, what protocols should be used, and how.
  656.  
  657. The drop receiver may decide that it wants something encoded as TEXT,
  658. followed by something encoded as COMPOUND_TEXT, and then by something in
  659. STRING format (beats me why, though...). it signals this by a (Tcl) list of
  660. dropTransfer pairs, consisting of the protocol (as an X atom name) and the
  661. widget that is being dropped on. Huh? Why the widget that is being dropped
  662. on? Because when a drop on a widget takes place, this is actually dealt
  663. with by the dragContext widget, and this is about to hand the transfer over
  664. to a transferWidget. Yes, I know you are using Tcl because you couldn't
  665. handle triple indirections (or rather, don't want too!), but they occur
  666. anyway... So here is a simple dragProc:
  667.  
  668. proc startDrop {dragContext} {
  669.   $dragContext dropTransferStart \
  670.         -dropTransfers {{COMPOUND_TEXT .l}} \
  671.         -numDropTransfers 1 \
  672.         -transferProc {doTransfer %closure {%value}}    
  673. }
  674.  
  675. The dragContext widget uses the command dropTransferStart to signal the
  676. beginning of the information transfer (it could also signal that the drop
  677. is to terminate, with no information transfer).  It will accept one chunk of
  678. information in the COMPOUND_TEXT format, and pass this on to the .l widget.
  679. The information transfer is actually carried on by the Tcl procedure in the
  680. transferProc resource. The only formats currently accepted (because they
  681. are hard-coded into Tm) are COMPOUND_TEXT, TEXT and STRING.
  682.  
  683. The transferProc resource is a function that is called when the drop
  684. receiver actually gets the information dropped on it. This should take at
  685. least two parameters. The %value is substituted for the actual information
  686. dropped on it, and %closure is the second element in the dropTransfer list
  687. which should be the widget the drop is happening on. (Why not let Tm
  688. determine this? I dunno. Consistency with Motif doco? Brain damage late at
  689. night?) Then the dropped on widget can take suitable action. This function
  690. resets the label to the text dropped on it:
  691.  
  692. proc doTransfer {destination value} {
  693.   $destination setValues -labelString $value
  694. }
  695.  
  696. where destination is substituted by %closure and value by %value.
  697.  
  698. Send
  699.  
  700. Tk has a primitive called ``send''. In this, each interpreter has a name,
  701. and you can send tcl commands from one interpreter to another. When an
  702. interpreter receives a sent command it executes it, and returns any result
  703. back to the original interpreter. This mechanism is also available to 
  704. tm, so that Motif applications can set commands to other Motif applications,
  705. and also to and from Tk ones.
  706.  
  707. If a tm application succeeds in registering its name,
  708. from then on, it can send to another. For example,
  709.  
  710. send interp2 {puts stdout "hello there"}
  711.  
  712. instructs ``interp2'' to display a message.
  713.  
  714. Automated testing
  715.  
  716. Tcl uses an automated test system that can run regression tests on a system.
  717. it does so by ``sourcing'' a file containing a set of test procedures,
  718. including a procedure called ``test''. This takes 4 arguments: the first is
  719. the name of the test, the second is a textual description of the test, the
  720. third is the code to execute to perform the test, and the last is the
  721. expected result. The ``test'' procedure runs the test and if the actual
  722. result differs from the expected one, an error message is printed.
  723.  
  724. This mechanism is used well for the tcl core. It is also used for Tk, but
  725. with less success: while good for batch mode testing, it does not handle
  726. the interactive nature of GUI environments. To perform batch mode testing
  727. in such environments, one needs to be able to create input events to
  728. simulate an interactive user.
  729.  
  730. One approach is to create raw X events and to feed them directly into the
  731. Xt event loop handler. This requires a very low-level knowledge of what is
  732. going on, and anyway does not reflect the object structure of the Xt
  733. toolkit. Each widget defines a set of ``actions'' that are intended to be
  734. the ``public'' interface of that widget. This is the hook that the tclMotif
  735. test procedures use to extend the tcl testing into this GUI environment.
  736.  
  737. A command for any widget is ``callActionProc''. This takes an argument
  738. which is the name of the action for the widget. For example, a button has
  739. an Arm action, so this can be invoked by
  740.  
  741. .btn callActionProc Arm
  742.  
  743. This will perform the visual behaviour for this action, and also call any
  744. callbacks associated with this action.
  745.  
  746. In an ideal world, this would be enough. Some parts of Motif are not quite
  747. ideal yet. For example, the Activate action is, by default, invoked by
  748. releasing the mouse button after it has been pressed within a PushButton.
  749. The association between user action and widget action is controllable
  750. through the translation tables for that widget, so these could be - to be
  751. bizarre - set up so that pressing d (for down) arms the button, while
  752. pressing u (for u) activates it. Motif (at 1.2.1 anyway) refuses to admit
  753. this possibility and is hard-coded to assume  that the action came from a
  754. ButtonRelease. The reason is simple: if the release occurs within the
  755. PushButton, it means that the action was desired; if it occurs outside the
  756. PushButton then the user has cancelled the action by moving out of the
  757. widget. So it has to be a mouse event for this model to be followed.
  758.  
  759. For tests, this means that you cannot just issue an Activate action. You do
  760. have to prepare an X button event to the extent of setting the x and y
  761. coordinates so that the internal Motif function can determine whether or
  762. not to invoke the callbacks. This looks like:
  763.  
  764. .btn callActionProc Activate \
  765.     -type ButtonPress \
  766.     -x 0 -y 0
  767.  
  768. to be within the widget, or
  769.  
  770. .btn getValues -width w -height h
  771. set big_h [expr {2 * $h}]
  772. set big_w [expr {2 * $w}]
  773. .btn callActionProc Activate \
  774.     -type ButtonPress \
  775.     -x $big_w -y $big_h
  776.  
  777. to be outside the widget.
  778.  
  779.